//
//  NoteMigration.swift
//  hello
//
//  Created by 赵康 on 2024/11/11.
//

import Fluent
import FluentSQL

extension Note {
	struct Migration: AsyncMigration {
		var name: String { "NoteMigration" }
		
		func prepare(on database: any Database) async throws {
			try await database.schema(Note.schema)
				.id()
				.field(Note.FieldKeys.content, .sql(.text))
				.field(Note.FieldKeys.user, .uuid, .references(User.schema, .id))
				.field(Note.FieldKeys.audio, .uuid, .references(Audio.schema, .id))
				.field(Note.FieldKeys.createdAt, .datetime, .required)
				.field(Note.FieldKeys.updatedAt, .datetime, .required)
				.create()
		}
		func revert(on database: any Database) async throws {
			try await database.schema(Note.schema).delete()
		}
	}
}

extension Note {
  struct AddTimestampAndTagsToNote: AsyncMigration {
    var name: String { "AddTimestampAndTagsToNote" }
    
    func prepare(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .field(FieldKeys.timestamp, .double, .sql(.default(0.0)))
        .field(FieldKeys.tags, .array(of: .string)) // 移除默认值
        .field(FieldKeys.isPublic, .bool, .sql(.default(true)))
        .update()
    }
    
    func revert(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .deleteField(FieldKeys.timestamp)
        .deleteField(FieldKeys.tags)
        .deleteField(FieldKeys.isPublic)
        .update()
    }
  }
}

extension Note {
  struct AddLikeInformation: AsyncMigration {
    var name: String { "addLikeInformation" }
    
    func prepare(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .field(FieldKeys.likedBy, .array(of: .uuid))
        .field(FieldKeys.likeCount, .int, .sql(.default(0)))
        .update()
    }
    
    func revert(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .deleteField(FieldKeys.likedBy)
        .deleteField(FieldKeys.likeCount)
        .update()
    }
  }
}

extension Note {
  struct UpdateContentFieldType: AsyncMigration {
    var name: String { "UpdateContentFieldType" }
    
    func prepare(on database: Database) async throws {
        // 针对 MySQL 修改字段类型为 MEDIUMTEXT
      let query = database is SQLDatabase ?
      "ALTER TABLE \(Note.schema) MODIFY content MEDIUMTEXT" :
      ""
      
      if !query.isEmpty {
        return try await (database as! SQLDatabase).raw(SQLQueryString(query)).run()
      }
    }
    
    func revert(on database: Database) async throws {
        // 如果需要回滚，将类型改回 TEXT
      let query = database is SQLDatabase ?
      "ALTER TABLE \(Note.schema) MODIFY content TEXT" :
      ""
      
      if !query.isEmpty {
        return try await (database as! SQLDatabase).raw(SQLQueryString(query)).run()
      }
    }
  }
}

extension Note {
  struct AddReviewStatus: AsyncMigration {
    var name: String { "AddReviewStatus" }
    
    func prepare(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .field(
          FieldKeys.reviewStatus,
          .string,
          .sql(.default(ReviewStatus.none.rawValue))
        )
        .update()
    }
    
    func revert(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .deleteField(FieldKeys.reviewStatus)
        .update()
    }
  }
}

extension Note {
  struct AddAnswerAndArabicFields: AsyncMigration {
    var name: String { "AddAnswerAndArabicFields" }
    
    func prepare(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .field(FieldKeys.answer, .string)
        .field(FieldKeys.isArabic, .bool, .sql(.default(true)))
        .field(FieldKeys.isAnswerArabic, .bool, .sql(.default(false)))
        .update()
    }
    
    func revert(on database: Database) async throws {
      try await database.schema(SchemaEnum.notes.rawValue)
        .deleteField(FieldKeys.answer)
        .deleteField(FieldKeys.isArabic)
        .deleteField(FieldKeys.isAnswerArabic)
        .update()
    }
  }
}
